package com.qsmx.store.app.util;

import android.content.Context;
import android.os.Bundle;

import com.qsmx.store.app.entity.BaseEvent;
import com.qsmx.store.app.event.CardReadEvent;
import com.qsmx.store.app.event.CardWriteEvent;
import com.sunmi.reader.usbhid.SunmiReader;

import org.greenrobot.eventbus.EventBus;

import java.util.Arrays;
import java.util.Date;

import static android.os.SystemClock.sleep;

public class CardReadUtil {

    public static SunmiReader sunmireader = new SunmiReader();
    private static int ret;
    private static byte[] sv;
    private static byte[] hv;
    private static byte[] iso14443auid;
    private static byte[] type;
    private static int count;
    private static char tag;
    private static StringBuffer sbCardNum;
    private static String cardNum;
    private static Bundle bundle = new Bundle();
    private static char defaultTag = 0x04;
    private String writedata;

    public static void StartGetCardNum(final Context context, char mTag, final BaseEvent event) {
        defaultTag = mTag;

        iso14443auid = new byte[10];
        type = new byte[50];
        sv = new byte[50];
        hv = new byte[50];
        count = 0;
        sbCardNum = new StringBuffer();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                tag = 0;
                if (!sunmireader.isOpen()) {
                    ret = sunmireader.open(context);
                    if (ret < -1) {
                        sbCardNum.append("1. 未检测到读写器");
                        bundle.putString("cardNum", sbCardNum.toString());
                        event.setData(bundle);
                        EventBus.getDefault().post(event);
                        return;
                    }
                }
                sunmireader.beepTime((char) 100);
                Arrays.fill(iso14443auid, (byte) 0);
//                sbCardNum.append("1. 成功打开读写器\n");

                ret = sunmireader.getReaderType(type);
                if (ret < 0) {
                    sbCardNum.append("获取读写器型号失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    return;
                }
//                sbCardNum.append("读写器型号:");
//                sbCardNum.append(BytestoASCII(type, ret));
//                sbCardNum.append(";");

                ret = sunmireader.getReaderSoftwareVersion(sv);
                if (ret < 0) {
                    sbCardNum.append("获取读写器软件版本失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    sunmireader.close();
                    return;
                }

//                sbCardNum.append("软件版本: ");
//                sbCardNum.append(BytestoASCII(sv, ret));
//                sbCardNum.append(";");

                ret = sunmireader.getReaderHardwareVersion(hv);
                if (ret < 0) {
                    sbCardNum.append("获取读写器硬件版本失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    sunmireader.close();
                    return;
                }

//                sbCardNum.append("硬件版本: ");
//                sbCardNum.append(BytestoASCII(hv, ret));
//                sbCardNum.append("\n");
//                sbCardNum.append("读取中...\n");

                Date dateold = new Date();
                Long timeold = dateold.getTime();
                Long timenew = timeold;
                while ((timenew - timeold) / 1000 < 3) {

                    if (!sunmireader.isOpen()) {
                        if (count >= 3) {
                            sbCardNum.append("读取异常");
                            bundle.putString("cardNum", sbCardNum.toString());
                            event.setData(bundle);
                            EventBus.getDefault().post(event);
                            sunmireader.close();
                            return;
                        } else {
                            sleep(50);
                            count++;
                            continue;
                        }
                    }
                    count = 0;
                    ret = ISO14443ACheckCard();
                    if (ret == 0) {
                        bundle.putString("cardNum", sbCardNum.toString());
                        event.setData(bundle);
                        EventBus.getDefault().post(event);
                        sunmireader.close();
                        return;
                    }

//                    sbCardNum.append("\n读取中...\n");

                    Date datenew = new Date();
                    timenew = datenew.getTime();
                }
//                sbCardNum.append("\n读取中...\n");
//                sbCardNum.append("\n读取失败，超时...");
                bundle.putString("cardNum", sbCardNum.toString());
                event.setData(bundle);
                EventBus.getDefault().post(event);
                sunmireader.close();
                return;
            }
        });
        thread.start();
    }

    public static void StartWriteCardNum(final Context context, final String writeCardNum, char mTag, final BaseEvent event) {
        defaultTag = mTag;

        iso14443auid = new byte[10];
        type = new byte[50];
        sv = new byte[50];
        hv = new byte[50];
        count = 0;
        sbCardNum = new StringBuffer();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                tag = 0;
                if (!sunmireader.isOpen()) {
                    ret = sunmireader.open(context);
                    if (ret < -1) {
                        sbCardNum.append("1. 未检测到读写器");
                        bundle.putString("cardNum", sbCardNum.toString());
                        event.setData(bundle);
                        EventBus.getDefault().post(event);
                        return;
                    }
                }
                sunmireader.beepTime((char) 100);
                Arrays.fill(iso14443auid, (byte) 0);
//                sbCardNum.append("1. 成功打开读写器\n");

                ret = sunmireader.getReaderType(type);
                if (ret < 0) {
                    sbCardNum.append("获取读写器型号失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    sunmireader.close();
                    return;
                }
//                sbCardNum.append("读写器型号:");
//                sbCardNum.append(BytestoASCII(type, ret));
//                sbCardNum.append(";");

                ret = sunmireader.getReaderSoftwareVersion(sv);
                if (ret < 0) {
                    sbCardNum.append("获取读写器软件版本失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    sunmireader.close();
                    return;
                }

//                sbCardNum.append("软件版本: ");
//                sbCardNum.append(BytestoASCII(sv, ret));
//                sbCardNum.append(";");

                ret = sunmireader.getReaderHardwareVersion(hv);
                if (ret < 0) {
                    sbCardNum.append("获取读写器硬件版本失败");
                    bundle.putString("cardNum", sbCardNum.toString());
                    event.setData(bundle);
                    EventBus.getDefault().post(event);
                    sunmireader.close();
                    return;
                }

//                sbCardNum.append("硬件版本: ");
//                sbCardNum.append(BytestoASCII(hv, ret));
//                sbCardNum.append("\n");
//                sbCardNum.append("读取中...\n");

                Date dateold = new Date();
                Long timeold = dateold.getTime();
                Long timenew = timeold;
                while ((timenew - timeold) / 1000 < 10) {

                    if (!sunmireader.isOpen()) {
                        if (count >= 3) {
                            sbCardNum.append("读取异常");
                            bundle.putString("cardNum", sbCardNum.toString());
                            event.setData(bundle);
                            EventBus.getDefault().post(event);
                            sunmireader.close();
                            return;
                        } else {
                            sleep(50);
                            count++;
                            continue;
                        }
                    }
                    count = 0;
                    ret = ISO14443ACheckCardAndWrite(writeCardNum);
                    if (ret == 0) {
                        bundle.putString("cardNum", sbCardNum.toString());
                        event.setData(bundle);
                        EventBus.getDefault().post(event);
                        sunmireader.close();
                        return;
                    }

//                    sbCardNum.append("\n读取中...\n");

                    Date datenew = new Date();
                    timenew = datenew.getTime();
                }
//                sbCardNum.append("\n读取中...\n");
//                sbCardNum.append("\n读取失败，超时...");
                bundle.putString("cardNum", sbCardNum.toString());
                event.setData(bundle);
                EventBus.getDefault().post(event);
                sunmireader.close();
                return;
            }
        });
        thread.start();
    }

    public static int ISO14443ACheckCard() {

        byte[] types = new byte[2];
        byte[] uid = new byte[10];

        if (type[0] == 'R' && type[1] == '3' && type[2] == '2' && type[3] == '1' && type[4] == 'S' && type[5] == 'T') {
            for (int i = 0; i < 3; ++i) {
                ret = sunmireader.iso14443ACheckCard(true, uid, types);
                if (ret < 0) continue;
                break;
            }
        } else {
            ret = sunmireader.iso14443ACheckCard(false, uid, types);
        }

        if (ret > 0) {
            if (Arrays.equals(iso14443auid, uid)) return 0;
            sunmireader.beepTime((char) 100);

//            sbCardNum.append("\n开始寻找非接ISO14443A的卡");

            if (types[0] == 0x04 && types[1] == 0x00) {

//                sbCardNum.append("2. 寻找到UID为");
//                sbCardNum.append(BytestoHexString(uid, ret));
//                sbCardNum.append("的卡片\n卡片协议类型：ISO14443A，卡片类型：M1 S50卡\n");
//                sbCardNum.append("3. 开始操作卡片：\n");
//                sbCardNum.append("开始读取块数据：\n读取块地址为0x04，");

                byte[] key = HexStringtoBytes("5365616c79ff");
                ret = sunmireader.iso14443AM1Auth((byte) 0, (byte) defaultTag, key);
                if (ret < 0) {
                    sbCardNum.append("认证失败");
                    tag |= defaultTag;
                    return 0;
                }
                byte[] readblock = new byte[16];
                ret = sunmireader.iso14443AM1ReadBlock((byte) defaultTag, readblock);
                if (ret < 0) {
                    sbCardNum.append("读取数据失败");
                    tag |= defaultTag;
                    return 0;
                }
//                sbCardNum.append("读取数据成功，数据为");
                sbCardNum.append(BytestoHexString(readblock, readblock.length));
//                bundle.putString("cardNum", sbCardNum.toString());
                bundle.putString("cardStatus", "1");
                bundle.putChar("tag", defaultTag);
//                EventBus.getDefault().post(new CardReadEvent(bundle));

            } else {
                sbCardNum.append("卡片不符合iso14443A协议");
                tag |= defaultTag;
                return 0;
            }

            sunmireader.iso14443AHalt();
            tag |= defaultTag;
            return 0;
        } else {
        }

        tag &= 0xFFFE;
        return -1;
    }

    public static int ISO14443ACheckCardAndWrite(String writeData) {

        byte[] types = new byte[2];
        byte[] uid = new byte[10];

        if (type[0] == 'R' && type[1] == '3' && type[2] == '2' && type[3] == '1' && type[4] == 'S' && type[5] == 'T') {
            for (int i = 0; i < 3; ++i) {
                ret = sunmireader.iso14443ACheckCard(true, uid, types);
                if (ret < 0) continue;
                break;
            }
        } else {
            ret = sunmireader.iso14443ACheckCard(false, uid, types);
        }

        if (ret > 0) {
            if (Arrays.equals(iso14443auid, uid)) return 0;
            sunmireader.beepTime((char) 100);

//            sbCardNum.append("\n开始寻找非接ISO14443A的卡");

            if (types[0] == 0x04 && types[1] == 0x00) {

//                sbCardNum.append("2. 寻找到UID为");
//                sbCardNum.append(BytestoHexString(uid, ret));
//                sbCardNum.append("的卡片\n卡片协议类型：ISO14443A，卡片类型：M1 S50卡\n");
//                sbCardNum.append("3. 开始操作卡片：\n");
//                sbCardNum.append("开始读取块数据：\n读取块地址为0x04，");

                byte[] key = HexStringtoBytes("5365616c79ff");
                ret = sunmireader.iso14443AM1Auth((byte) 0, (byte) defaultTag, key);
                if (ret < 0) {
                    sbCardNum.append("认证失败");
                    tag |= defaultTag;
                    return 0;
                }
                byte[] readblock = new byte[16];
                ret = sunmireader.iso14443AM1ReadBlock((byte) defaultTag, readblock);
                if (ret < 0) {
                    sbCardNum.append("读取数据失败");
                    tag |= defaultTag;
                    return 0;
                }
//                sbCardNum.append("读取数据成功，数据为");
                byte[] writeblock = HexStringtoBytes(writeData);
                ret = sunmireader.iso14443AM1WriteBlock((byte) defaultTag, writeblock);
                if (ret < 0) {
                    sbCardNum.append("写入数据失败");
                    tag |= defaultTag;
                    return 0;
                }
                sunmireader.iso14443AM1ReadBlock((byte) defaultTag, readblock);
                sbCardNum.append(BytestoHexString(readblock, readblock.length));
//                bundle.putString("cardNum", sbCardNum.toString());
                bundle.putString("cardStatus", "1");
//                EventBus.getDefault().post(new CardWriteEvent(bundle));

            } else {
                sbCardNum.append("卡片不符合iso14443A协议");
                tag |= defaultTag;
                return 0;
            }

            sunmireader.iso14443AHalt();
            tag |= defaultTag;
            return 0;
        } else {
        }

        tag &= 0xFFFE;
        return -1;
    }

    public static final String BytestoASCII(byte[] data, int len) {
        int i;
        int j;
        StringBuffer tStringBuf = new StringBuffer();

        char[] tChars = new char[len];

        for (i = 0; i < len; i++) {
            tChars[i] = (char) data[i];
        }

        tStringBuf.append(tChars);

        return tStringBuf.toString();
    }


    public static final byte[] HexStringtoBytes(String hexString) {
        hexString = hexString.toLowerCase();
        final byte[] byteArray = new byte[hexString.length() / 2];
        int k = 0;
        for (int i = 0; i < byteArray.length; i++) {
            byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
            byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
            byteArray[i] = (byte) (high << 4 | low);
            k += 2;
        }
        return byteArray;
    }


    public static final String BytestoHexString(byte[] bArray, int len) {
        StringBuffer sb = new StringBuffer(len);
        String sTemp;

        for (int i = 0; i < len; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) sb.append(0);
            sb.append(sTemp.toUpperCase());
        }

        return sb.toString();
    }

    /**
     * 16进制转Ascii
     *
     * @param hexStr
     * @return
     */
    public static String HexToAscii(String hexStr) {
        StringBuilder output = new StringBuilder("");
        for (int i = 0; i < hexStr.length(); i += 2) {
            String str = hexStr.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }

}
